package com.jiangli.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jiangli.entity.Dish;
import com.jiangli.entity.UserPreference;
import com.jiangli.mapper.UserPreferenceMapper;
import com.jiangli.service.UserPreferenceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.type.TypeReference;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.sql.Timestamp;
import java.util.Map;

import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class UserPreferenceServiceImpl implements UserPreferenceService {
    @Autowired
    private UserPreferenceMapper preferenceMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private ObjectMapper objectMapper;

    private static final String PREFERENCE_KEY = "user:preference:";
    @Override
    public void recordUserAction(Long userId, Dish dish, String action) {
        UserPreference preference = getOrCreatePreference(userId);
        String weightsStr = preference.getCategoryWeights();
        //TODO 序列化map'
        HashMap<String,Double> weights =
                null;
        try {
            weights = objectMapper.readValue(weightsStr, new TypeReference<HashMap<String,Double>>(){});
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        // 根据行为类型计算权重增量
        double increment = getIncrementByAction(action);
        String dishId = dish.getId().toString();

        // 更新权重（上限1.0）
        double newWeight = Math.min(1.0, weights.getOrDefault(dishId, 0.0) + increment);
        weights.put(dishId, newWeight);
        try {
            String weightsStr2 = objectMapper.writeValueAsString(weights);
            preference.setCategoryWeights(weightsStr2);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        preference.setUpdateTime(LocalDateTime.now());

        // 保存到数据库和缓存
        preferenceMapper.update(preference);
        savePreferenceToRedis(userId, preference);
    }

    @Override
    public UserPreference getPreference(Long userId) {
        String json = redisTemplate.opsForValue().get(PREFERENCE_KEY + userId);
        if (json != null) {
            try {
                return objectMapper.readValue(json, UserPreference.class);
            } catch (JsonProcessingException e) {
                redisTemplate.delete(PREFERENCE_KEY + userId);
            }
        }

        UserPreference preference = preferenceMapper.selectByUserId(userId);
        if (preference == null) {
            preference = createDefaultPreference(userId);
        } else {
            savePreferenceToRedis(userId, preference);
        }
        return preference;

    }
    private double getIncrementByAction(String action) {
        return switch (action) {
            case "click" -> 0.1;
            case "collect" -> 0.5;
            default -> 0.0;
        };
    }

    private UserPreference getOrCreatePreference(Long userId) {
        UserPreference preference = getPreference(userId);
        return preference != null ? preference : createDefaultPreference(userId);
    }

    private UserPreference createDefaultPreference(Long userId) {
        UserPreference preference = new UserPreference();
        preference.setUserId(userId);

        // 关键修改：将HashMap转为JSON字符串
        try {
            // 创建默认的空Map，并序列化为JSON字符串
            String defaultWeights = objectMapper.writeValueAsString(new HashMap<>());
            preference.setCategoryWeights(defaultWeights); // 存入JSON字符串
        } catch (JsonProcessingException e) {
            // 处理JSON序列化异常（如日志记录、抛出业务异常等）
            throw new RuntimeException("初始化用户偏好失败：" + e.getMessage(), e);
        }

        preference.setUpdateTime(LocalDateTime.now());;
        preferenceMapper.insert(preference);
        savePreferenceToRedis(userId, preference);
        return preference;
    }

    private void savePreferenceToRedis(Long userId, UserPreference preference) {
        try {
            String json = objectMapper.writeValueAsString(preference);
            redisTemplate.opsForValue().set(PREFERENCE_KEY + userId, json, 24, TimeUnit.HOURS);
        } catch (JsonProcessingException e) {
            // 缓存失败不影响主流程
        }
    }
}
